<?php


namespace coco\exception;

use coco\App;
use coco\Config;
use coco\exception\ErrorException;
use coco\Response;
use coco\traits\Singleton;
use coco\Tree;
use Throwable;

/**
 * Class Handle
 * @package easy\exception
 */
class Handle
{
    use Singleton;

    private static function highlightText($text)
    {
        $text = highlight_string("<?php " . $text, true);
        $text = trim($text);
        $text = preg_replace("|^\\<code\\>\\<span style\\=\"color\\: #[a-fA-F0-9]{0,6}\"\\>|", "", $text, 1);  // remove prefix
        $text = preg_replace("|\\</code\\>\$|", "", $text, 1);  // remove suffix 1
        $text = trim($text);  // remove line breaks
        $text = preg_replace("|\\</span\\>\$|", "", $text, 1);  // remove suffix 2
        $text = trim($text);  // remove line breaks
        $text = preg_replace("|^(\\<span style\\=\"color\\: #[a-fA-F0-9]{0,6}\"\\>)(&lt;\\?php&nbsp;)(.*?)(\\</span\\>)|", "\$1\$3\$4", $text);  // remove custom added "<?php "

        return $text;
    }

    /**
     * @param Throwable $e
     */
    public function report(Throwable $e)
    {
        if (Config::getInstance()->get('app.debug')) {
            if ($e instanceof CustomException) {
                $e->response();
                return;
            }
            if(App::getInstance()->is_cli)
            {
                throw $e;
            }
            list($first, $source) = self::getScript($e);

            $html = '<code>';
            foreach ($source as $i => $line) {
                $html .= '<div style="' . (($first + $i === $e->getLine()) ? 'background-color: #ddd' : '') . '">' . '<span style="color: blue;margin-right: 20px">' . ($first + $i) . '</span>' . self::highlightText($line) . '</div>';
            }
            $html .= '</code>';
            $page = '<h2>Exception:' . $e->getMessage() . '</h2>';
            $page .= '<p>' . $e->getFile() . ':' . $e->getLine() . '</p>';
            $page .= $html;
            $page .= '<code>' . join('<br />', array_map([self::class, 'highlightText'], explode(PHP_EOL, $e->getTraceAsString()))) . '</code>';
            $response = new Response(['type' => 'html']);
            $response->setHeader('HTTP/1.1 404 Not Found');
            $response->setData(['html' => $page]);
            $response->send();
        } else {
            $response = new Response();
            $response->setHeader('HTTP/1.1 404 Not Found');
            $response->setData([
                'msg' => $e->getMessage(),
                'code' => $e->getCode(),
            ]);
            $response->send();
        }
    }
    public function error($errno, $errstr, $errfile, $errline, $errcontext){
        if (error_reporting() & $errno) {
            throw new ErrorException($errno, $errstr, $errfile, $errline);
        }

    }

    protected static function getScript(Throwable $e)
    {
        $contents = file($e->getFile());
        $line = $e->getLine();
        $first = ($line - 9 > 0) ? $line - 9 : 1;
        return [
            $first,
            array_slice($contents, $first - 1, 19)
        ];
    }


}